package org.shoukaiseki.common.utils;

import org.shoukaiseki.common.exception.MessageVirtualException;

import java.util.*;

public class ListUtils {

    /**
     * 获取list中的第一条记录,存在多条记录则抛异常
     * @param list
     * @param <T>
     * @return
     */
    public static <T> T findFirstMultipleRecordThrow(List<T> list){
        if(StringUtils.isEmpty(list)){
            return (T)null;
        }
        if(list.size()>1){
            throw new MessageVirtualException("获取详情时匹配到多条记录");
        }
        return list.stream().findFirst().orElse(null);
    }


    public static  <T> List<T> copyToList(Collection<T> list){
        ArrayList<T> newList = new ArrayList<>();
        newList.addAll(list);
        return newList;
    }

    public static <T> List<T> newArrayList(Collection col,Object... objs){
        ArrayList<T> list = new ArrayList<>();
        if (objs!=null) {
            for (Object obj : objs) {
                list.add((T)obj);
            }
        }
        list.addAll(col);
        return list;
    }

    public static  <T> List<T> newArrayList(Iterable<T> list){
        ArrayList<T> newList = new ArrayList<>();
        Iterator<T> it = list.iterator();
        while (it.hasNext()) {
            newList.add(it.next());
        }
        return newList;
    }

    public static <T> List<T> newArrayList(Object... objs){
        ArrayList<T> list = new ArrayList<>();
        if (objs!=null) {
            for (Object obj : objs) {
                list.add((T)obj);
            }
        }
        return list;
    }

    /**
     * 如果为null则返回一个空list,用于for循环时不需要判断 null
     * @param list
     * @param <T>
     * @return
     */
    public static <T> List<T> emptyIfNull(List<T> list) {
        return list == null ? Collections.emptyList() : list;
    }


    /**
     * 如果为null则返回一个空list,用于for循环时不需要判断 null
     * @param objs
     * @param <T>
     * @return
     */
    public static <T> List<T> emptyIfNull(T... objs) {
        if(StringUtils.isEmpty(objs)){
            return Collections.emptyList();
        }
        ArrayList list = new ArrayList();
        for (T obj : objs) {
            list.add(obj);
        }
        return list;
    }


    /**
     * Checks if all values in the array are not {@code nulls}.
     *
     * <p>
     * If any value is {@code null} or the array is {@code null} then
     * {@code false} is returned. If all elements in array are not
     * {@code null} or the array is empty (contains no elements) {@code true}
     * is returned.
     * </p>
     *
     * <pre>
     * ListUtils.anyNotEmpty([])            = false
     * ListUtils.anyNotEmpty([1],[2])       = true
     * ListUtils.anyNotEmpty(null)          = false
     * ListUtils.anyNotEmpty(null, [])      = false
     * ListUtils.anyNotEmpty(null, [1])     = true
     * ListUtils.anyNotEmpty([1], null)     = true
     * ListUtils.anyNotEmpty([1],[2],null)  = true
     * </pre>
     *
     * @param values  the values to test, may be {@code null} or empty
     * @return {@code false} if there is at least one {@code null} value in the array or the array is {@code null},
     * {@code true} if all values in the array are not {@code null}s or array contains no elements.
     * @since 3.5
     */
    public static boolean anyNotEmpty(final Collection<?>... values) {
        if (values == null) {
            return false;
        }

        for (final Collection val : values) {
            if (val != null&&!val.isEmpty()) {
                return true;
            }
        }

        return false;
    }

    public static boolean anyEmpty(final Collection<?>... values) {
        return !allNotEmpty(values);
    }


    /**
     * Checks if all values in the array are not {@code nulls}.
     *
     * <p>
     * If any value is {@code null} or the array is {@code null} then
     * {@code false} is returned. If all elements in array are not
     * {@code null} or the array is empty (contains no elements) {@code true}
     * is returned.
     * </p>
     *
     * <pre>
     * ListUtils.allNotEmpty([])            = false
     * ListUtils.allNotEmpty([1],[2])       = true
     * ListUtils.allNotEmpty(null)          = false
     * ListUtils.allNotEmpty(null, [])      = false
     * ListUtils.allNotEmpty(null, [1])     = false
     * ListUtils.allNotEmpty([1], null)     = false
     * ListUtils.allNotEmpty([1],[2],null)  = false
     * </pre>
     *
     * @param values  the values to test, may be {@code null} or empty
     * @return {@code false} if there is at least one {@code null} value in the array or the array is {@code null},
     * {@code true} if all values in the array are not {@code null}s or array contains no elements.
     * @since 3.5
     */
    public static boolean allNotEmpty(final Collection<?>... values) {
        if (values == null||values.length==0) {
            return false;
        }

        for (final Collection val : values) {
            if (val == null) {
                return false;
            }
            if(val.isEmpty()){
                return false;
            }
        }

        return true;
    }




    /**
     * Checks if all values in the array are not emptys.
     *
     * <pre>
     * ListUtils.anyNotEmpty([])            = false
     * ListUtils.anyNotEmpty([1],[2])       = true
     * ListUtils.anyNotEmpty(null)          = false
     * ListUtils.anyNotEmpty(null, [])      = false
     * ListUtils.anyNotEmpty(null, [1])     = true
     * ListUtils.anyNotEmpty([1], null)     = true
     * ListUtils.anyNotEmpty([1],[2],null)  = true
     * </pre>
     *
     * @param values  the values to test, may be {@code null} or empty
     * @return {@code false} if there is at least one {@code null} value in the array or the array is {@code null},
     * {@code true} if all values in the array are not {@code null}s or array contains no elements.
     * @since 3.5
     */
    public static boolean anyNotEmpty(final Object[]... values) {
        if (values == null) {
            return false;
        }

        for (final Object[] val : values) {
            if (val != null&&val.length!=0) {
                return true;
            }
        }

        return false;
    }

    public static String joinToStr(List list){
        return joinToStr(list,StringUtils.SEPARATOR_COMMA,StringUtils.NULLSTR);
    }

    public static String joinToStr(List list,String separatorChars){
        return joinToStr(list,separatorChars,StringUtils.NULLSTR);
    }

    public static String joinToStr(List list,String separatorChars,String emptyString){
        if(StringUtils.isEmpty(list)){
            return emptyString;
        }
        StringJoiner stringJoiner = new StringJoiner(separatorChars);
        for (Object tmp : list) {
            if(tmp==null){
               continue;
            }
            String str=StringUtils.trimToEmpty(tmp.toString());
            if(StringUtils.isNotEmpty(str)){
                stringJoiner.add(str);
            }
        }

        return stringJoiner.toString();
    }
}
